using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Data.Linq;
using System.Data.Linq.Mapping;
using System.Linq;
using System.Reflection;
using Magiq.Sql.Tests.TestModel;
using Magiq.Tests;
using Magiq.Tests.Support;

namespace Magiq.Sql.Tests
{
    public class MagiqToSqlTestConfigurator : IMagiqTestConfigurator
    {
        protected DataContext dataContext;

        static MagiqToSqlTestConfigurator()
        {
            Current = new MagiqToSqlTestConfigurator();
        }

        private MagiqToSqlTestConfigurator()
        {
        }

        public static MagiqToSqlTestConfigurator Current { get; private set; }

        #region IMagiqTestConfigurator Members

        public void Persist<T>(IList<T> items) where T : class
        {
            dataContext.GetTable<T>().InsertAllOnSubmit(items);
            dataContext.SubmitChanges();
        }

        public void SetUp()
        {
            Magiq.Clear()
                .NoDefault()
                .Register<MagiqMock>()
                .Register<MagiqToSql>();

            CreateDataContext();

            if (dataContext.DatabaseExists())
                dataContext.DeleteDatabase();
            dataContext.CreateDatabase();
        }

        public void TearDown()
        {
            CloseDataContext();
        }

        public IQueryable<T> GetQueryable<T>() where T : class
        {
            return dataContext.GetTable<T>();
        }


        public void Reload()
        {
            dataContext.SubmitChanges();
            CloseDataContext();
            CreateDataContext();
        }

        #endregion

        private void CreateDataContext()
        {
            var mapping = Assembly.GetExecutingAssembly().GetManifestResourceStream("Magiq.Sql.Tests.Mappings.xml");
            var mappingSource = XmlMappingSource.FromStream(mapping);

            dataContext = new DataContext(ConfigurationManager.ConnectionStrings["SqlServer"].ConnectionString,
                                          mappingSource)

                              {
                                  DeferredLoadingEnabled = true
                              };
            var o = new DataLoadOptions();
            o.LoadWith<LinqToSqlTestClass1>(x => x.Reference);
            o.LoadWith<LinqToSqlTestClass1>(x => x.Reference2);
            o.LoadWith<CompositePkParent>(x => x.Child);

            dataContext.LoadOptions = o;
        }

        private void CloseDataContext()
        {
            var c = dataContext.Connection;
            if (c.State != ConnectionState.Closed)
                c.Close();
            dataContext.Dispose();
            c.Dispose();
        }
    }
}